#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
测试用例执行脚本
根据输入的测试用例路径，自动找到对应的 module 并执行测试命令
"""

import os
import sys
import json
import re
import subprocess
from pathlib import Path


def find_project_root(test_case_path):
    """
    根据测试用例路径，向上查找项目根目录（包含 build-profile.json5 的目录）
    """
    path = Path(test_case_path).resolve()
    
    # 如果是文件，先获取其目录
    if path.is_file():
        path = path.parent
    
    # 向上查找 build-profile.json5，保留“最外层”的那个
    current = path
    outermost_root = None
    while True:
        build_profile = current / "build-profile.json5"
        if build_profile.exists():
            outermost_root = current  # 不立即返回，继续向上直到根目录
        if current == current.parent:
            break
        current = current.parent

    if outermost_root:
        return outermost_root
    
    raise FileNotFoundError("无法找到项目根目录（包含 build-profile.json5 的目录）")


def remove_json5_comments(content):
    """
    移除 JSON5 文件中的注释
    处理单行注释 (//) 和块注释 (/* */)
    """
    # 移除单行注释
    lines = content.split('\n')
    cleaned_lines = []
    for line in lines:
        # 检查是否在字符串中
        in_string = False
        escape_next = False
        result = []
        i = 0
        while i < len(line):
            char = line[i]
            if escape_next:
                result.append(char)
                escape_next = False
            elif char == '\\':
                result.append(char)
                escape_next = True
            elif char == '"' or char == "'":
                result.append(char)
                in_string = not in_string
            elif not in_string and char == '/' and i + 1 < len(line):
                if line[i + 1] == '/':
                    # 单行注释，忽略剩余部分
                    break
                elif line[i + 1] == '*':
                    # 块注释开始
                    i += 2
                    while i < len(line) - 1:
                        if line[i] == '*' and line[i + 1] == '/':
                            i += 2
                            break
                        i += 1
                    continue
                else:
                    result.append(char)
            else:
                result.append(char)
            i += 1
        cleaned_lines.append(''.join(result))
    
    content = '\n'.join(cleaned_lines)
    
    # 移除块注释（跨行）
    pattern = r'/\*.*?\*/'
    content = re.sub(pattern, '', content, flags=re.DOTALL)
    
    return content


def remove_trailing_commas(content: str) -> str:
    """
    JSON5 支持的末尾逗号在标准 JSON 中不合法，需要移除
    """
    # 先处理对象/数组结尾处的逗号
    trailing_comma_pattern = r',(\s*[}\]])'
    content = re.sub(trailing_comma_pattern, r'\1', content)
    return content


def parse_build_profile(build_profile_path):
    """
    解析 build-profile.json5 文件
    """
    with open(build_profile_path, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # 移除注释
    content = remove_json5_comments(content)
    # 移除末尾逗号
    content = remove_trailing_commas(content)
    
    # 解析 JSON
    try:
        data = json.loads(content)
        return data
    except json.JSONDecodeError as e:
        raise ValueError(f"解析 build-profile.json5 失败: {e}")


def find_module_name(test_case_path, build_profile_data):
    """
    根据测试用例路径，在 build-profile.json5 中找到对应的 module name
    """
    test_case_path = Path(test_case_path).resolve()
    modules = build_profile_data.get('modules', [])
    
    # 将测试用例路径转换为相对于项目根目录的路径
    project_root = Path(build_profile_data.get('_project_root', '.'))
    try:
        relative_path = test_case_path.relative_to(project_root)
    except ValueError:
        raise ValueError(f"测试用例路径不在项目根目录下: {test_case_path}")
    
    # 规范化相对路径（统一使用正斜杠）
    relative_path_str = str(relative_path).replace('\\', '/')
    
    # 尝试匹配每个 module 的 srcPath
    best_match = None
    best_match_length = 0
    
    for module in modules:
        module_name = module.get('name')
        src_path = module.get('srcPath', '')
        
        if not src_path:
            continue
        
        # 规范化 srcPath（移除 ./ 前缀，统一使用正斜杠，移除尾部斜杠）
        src_path_normalized = src_path.replace('./', '').replace('\\', '/').rstrip('/')
        
        # 检查测试用例路径是否在该 module 的 srcPath 下
        # 需要确保是完整的路径段匹配，而不是部分匹配
        if relative_path_str.startswith(src_path_normalized + '/') or relative_path_str == src_path_normalized:
            # 选择最长的匹配（最具体的）
            if len(src_path_normalized) > best_match_length:
                best_match = module_name
                best_match_length = len(src_path_normalized)
    
    if best_match:
        return best_match
    
    raise ValueError(f"无法找到测试用例路径对应的 module: {test_case_path}\n"
                     f"相对路径: {relative_path_str}\n"
                     f"可用的 modules: {[m.get('name') for m in modules]}")


def execute_command(command, project_root):
    """
    在项目根目录执行命令
    """
    print(f"执行命令: {command}")
    print(f"工作目录: {project_root}")
    print("-" * 80)
    
    # 切换到项目根目录执行命令
    result = subprocess.run(
        command,
        shell=True,
        cwd=project_root,
        capture_output=False,
        text=True
    )
    
    return result.returncode


def main():
    """
    主函数
    """
    if len(sys.argv) < 2:
        print("用法: python run_test.py <测试用例路径>")
        print("示例: python run_test.py D:\\CangjieAgent\\03_projects\\RentAndBuy1\\commons\\foundation\\src\\ohosTest\\ets\\test\\map_surrounding_feature.test.ets")
        sys.exit(1)
    
    test_case_path = sys.argv[1]
    
    try:
        # 1. 找到项目根目录
        print(f"测试用例路径: {test_case_path}")
        project_root = find_project_root(test_case_path)
        print(f"项目根目录: {project_root}")
        
        # 2. 读取并解析最外层的 build-profile.json5
        build_profile_path = project_root / "build-profile.json5"
        print(f"读取配置文件: {build_profile_path}")
        build_profile_data = parse_build_profile(build_profile_path)
        build_profile_data['_project_root'] = project_root
        
        # 3. 找到对应的 module name
        module_name = find_module_name(test_case_path, build_profile_data)
        print(f"匹配到的 module: {module_name}")

        task = 'buildHap' if 'ohosTest' in str(Path(test_case_path).parent) else 'genOnDeviceTestHap'
        
        # 4. 拼接命令
        command = f"hvigorw --mode module -p module={module_name}@ohosTest -p isOhosTest=true -p product=default -p buildMode=test {task} --analyze=normal --parallel --incremental --daemon --error"

        # 5. 执行命令
        return_code = execute_command(command, project_root)
        
        if return_code == 0:
            print("命令执行成功")
        else:
            print(f"命令执行失败，返回码: {return_code}")
            sys.exit(return_code)
            
    except Exception as e:
        print(f"错误: {e}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()

